/**
 * 简版的promsie
 * @param {function} fn  一般写法（resolve,reject)=>{} 
 */
function myPromise(fn) {
  const that = this // this指向实例化后的新对象
  that.state = 'pending' // promise状态
  that.value = null  // resolve 或 reject传入的参数
  that.resovleCallbacks = [] // resovle 回调函数
  that.rejectClasbacks = [] // reject 回调函数
  
  // 对传入函数进行处理
  try {
    // 调用对应的resolve,reject处理函数
    fn(resolve, reject)
  } catch (e) { // 执行错误捕获
    reject(e)
  }

  // resolve 函数
  function resolve(value) {
    console.log('resolve 参数value:', value)

    // 判断传入的值是否为 `Promise` 类型
    if (value instanceof myPromise) {
      return value.then(resolve, reject)
    }

    setTimeout(()=>{
      if (that.state == 'pending') {
        // 模拟状态变更为resolved
        that.state = 'resolved' // 更改promise状态
        that.value = value
        that.resovleCallbacks.map( cb => cb(that.value))
        // console.log('resovleCallbacks', that.resovleCallbacks)
      }
    }, 0)
  }

  // reject函数
  function reject(value) {
    setTimeout(()=>{
      if (that.state == 'pending') {
        that.state = 'rejected'
        that.value = value
        that.rejectClasbacks.map( cb => cb(that.value))
      }
    }, 0)
  }
}

/**
 * 在promise原型上注册方法then
 * 对then进行处理, onFulfilled, onRejected 是.then的两个回调参数
 */
// 
myPromise.prototype.then = function(onFulfilled, onRejected) {
  console.log('then第一个参数：onFulfilled', onFulfilled)
  console.log('---------')
  const that = this
  // 参数是否是函数，不是函数穿件函数并赋值
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
  onRejected = typeof onRejected  === 'function' ? onRejected  : err => { throw err }

  if (that.state === 'pending') {
    return (promise2 = new myPromise((resolve, reject)=>{
      that.resovleCallbacks.push(()=>{
        try{
          const x = onFulfilled(that.value)
          resolutionProcedure(promise2, x, resolve, reject)
        } catch(err) {
          reject(err)
        }
      })

      that.rejectClasbacks.push(()=>{
        try{
          const x = onRejected(that.value)
          resolutionProcedure(promise2, x, resolve, reject)
        } catch(err) {
          reject(err)
        }
      })
    }))
  }

  // 当状态从pending变为resolved 时执行onfFullfilled回调函数
  if(that.state === 'resolved') {
    return (promise2 = new myPromise((resolve, reject)=>{
        setTimeout(()=>{
          try{
            const x = onFulfilled(that.value)
            resolutionProcedure(promise2, x, resolve, reject)
          } catch(err) {
            reject(err)
          }
        },0)
      }))
  }

  // 当状态从pending变为rejected 时执行onRejected回调函数
  if(that.state === 'rejected') {
    return (promise2 = new myPromise((resolve, reject)=>{
      setTimeout(()=>{
        try{
          const x = onRejected(that.value)
          resolutionProcedure(promise2, x, resolve, reject)
        } catch(err) {
          reject(err)
        }
      },0)
    }))
  }

  function resolutionProcedure(promise2, x, resolve, reject) {
    console.log('x',x, '---resolve:', resolve)
    if (promise2 === x) {
      return reject(new TypeError('Error'))
    }
    if (x instanceof myPromise) {
      x.then(function(value) {
          resolutionProcedure(promise2, value, resolve, reject)
      }, reject)
  }
    let called = false
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
      try {
        let then = x.then
        if (typeof then === 'function') {
          then.call(
            x,
            y => {
              if (called) return
              called = true
              resolutionProcedure(promise2, y, resolve, reject)
            },
            e => {
              if (called) return
              called = true
              reject(e)
            }
          )
        } else {
          resolve(x)
        }
      } catch (e) {
        if (called) return
        called = true
        reject(e)
      }
    } else {
      resolve(x)
    }


  }
}


// ___________________________________


// 实例化构造函数
let p = new myPromise((resolve, reject) => {
  setTimeout(()=>{
    reject(66666)
  }, 0)
})
console.log('promises实例结果：', p)
console.log('---------')
// promise 初始化结果为
// myPromise {
//   state: 'pending', 状态
//   value: null, resolve 或 reject传入的参数
//   resovleCallbacks: [], 
//   rejectClasbacks: [] 
// }

// 调用的是原型链是方法then
p.then(value => {
  console.log('第一个then成功输出结果：', value)
  return value + '我来拼个参数玩'
}).then(res => {
  console.log('第二个then成功输出结果：', res)
}).catch(err=>{
  console.log('err',err)
})